package com.platform.common.util.query;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;

import com.platform.common.util.query.constant.Operator;
import com.platform.common.util.query.constant.ResourceType;
import com.platform.common.util.query.vo.Condition;
import com.platform.common.util.query.vo.Fields;
import com.platform.common.util.query.vo.Group;
import com.platform.common.util.query.vo.Page;
import com.platform.common.util.query.vo.QueryDataVo;
import com.platform.common.util.query.vo.Root;

public class QueryUtils {

	/**
	 * 创建列查询条件
	 * 
	 * @param param
	 *            ：参数
	 * @param columnName
	 *            ：列名称
	 * @param filedOp
	 *            ：列关系运算符
	 * @param filedOpt
	 *            ：filed于其他filed之间关系符
	 * @return
	 */
	public static List<Fields> setFileList(String param, String columnName, Operator filedOp, Operator filedOpt) {
		List<Fields> filedList = new ArrayList<Fields>();
		if (StringUtils.isNotEmpty(param)) {
			String[] tmp = param.split(",");
			for (int i = 0; i < tmp.length; i++) {
				String code = tmp[i];
				if (i < tmp.length - 1) {
					Fields filed = QueryUtils.setFiles(columnName, filedOp, code, filedOpt);
					filedList.add(filed);
				}
			}
		}
		return filedList;
	}

	/**
	 * 创建查询列
	 * 
	 * @param field
	 *            :列名称
	 * @param op
	 *            :列关系运算符
	 * @param value
	 *            :列对应的值
	 * @param opt
	 *            :filed于其他filed之间关系符
	 * @return
	 */
	public static Fields setFiles(String field, Operator op, String value, Operator opt) {
		Fields Fields = new Fields(field, op, value, opt);
		return Fields;
	}

	/**
	 * 创建查询列
	 * 
	 * @param field
	 *            :列名称
	 * @param op
	 *            :列关系运算符
	 * @param value
	 *            :列对应的值
	 * @return
	 */
	public static Fields setFiles(String field, Operator op, String value) {
		Fields Fields = new Fields(field, op, value);
		return Fields;
	}

	/**
	 * 创建查询列
	 * 
	 * @param field
	 *            ：查询列封装数据
	 * @return
	 */
	public static List<Fields> setFilesToList(Fields... field) {
		if (field == null || field.length < 1) {
			return null;
		}
		List<Fields> list = new ArrayList<Fields>();
		for (Fields fields : field) {
			list.add(fields);
		}
		return list;
	}

	/**
	 * 创建查询列
	 * 
	 * @param field
	 *            :列名称
	 * @param op
	 *            :列关系运算符
	 * @param value
	 *            :列对应的值
	 * @return
	 */
	public static List<Fields> setFilesToList(String field, Operator op, String value) {
		Fields Fields = setFiles(field, op, value);
		List<Fields> list = setFilesToList(Fields);
		return list;
	}

	/**
	 * 创建分组查询条件
	 * 
	 * @param field
	 *            :列名称
	 * @param fieldOper
	 *            :列关系运算符
	 * @param fieldValue
	 *            :列对应的值
	 * @return
	 */
	public static Group setChildGroup(String field, Operator fieldOper, String fieldValue) {
		List<Fields> files = setFilesToList(field, fieldOper, fieldValue);
		Group group = new Group(files);
		return group;
	}

	/**
	 * 创建分组层级查询条件
	 * 
	 * @param field
	 *            :列名称
	 * @param fieldOper
	 *            :列关系运算符
	 * @param fieldValue
	 *            :列对应的值
	 * @param groupOper
	 *            :组与组之间关系
	 * @return
	 */
	public static Group setChildGroup(String field, Operator fieldOper, String fieldValue, Operator groupOper) {
		List<Fields> fields = setFilesToList(field, fieldOper, fieldValue);
		Group group = setGroup(fields, groupOper, null);
		return group;
	}

	/**
	 * 创建分组层级查询条件
	 * 
	 * @param field
	 *            :列名称
	 * @param fieldOper
	 *            :列关系运算符
	 * @param fieldValue
	 *            :列对应的值
	 * @param groupOper
	 *            :组与组之间关系
	 * @return
	 */
	public static Group setGroup(String field, Operator fieldOper, String fieldValue, Operator groupOper, Group group) {
		List<Fields> fields = setFilesToList(field, fieldOper, fieldValue);
		Group tgroup = setGroup(fields, groupOper, group);
		return tgroup;
	}

	/**
	 * 创建分组条件
	 * 
	 * @param param
	 *            ：参数
	 * @param columnName
	 *            ：列名称
	 * @param filedOp
	 *            ：列关系运算符
	 * @param filedOpt
	 *            ：filed于其他filed之间关系符
	 * @param groupOpt
	 *            ：分组关系符
	 * @return
	 */
	public static Group setGroup(String param, String columnName, Operator filedOp, Operator filedOpt, Operator groupOpt) {
		if (StringUtils.isEmpty(param)) {
			return null;
		}
		List<Fields> filedList = new ArrayList<Fields>();
		String[] tmp = param.split(",");
		for (int i = 0; i < tmp.length; i++) {
			String code = tmp[i];
			if (i < tmp.length - 1) {
				Fields filed = QueryUtils.setFiles(columnName, filedOp, code, filedOpt);
				filedList.add(filed);
			} else {
				Fields filed = QueryUtils.setFiles(columnName, filedOp, code, null);
				filedList.add(filed);
			}
		}
		Group group = setGroup(filedList, groupOpt);
		return group;
	}

	/**
	 * 创建分组查询条件
	 * 
	 * @param fields
	 *            :列封装数据
	 * @param groupOper
	 *            :组与组之间关系
	 * @return
	 */
	public static Group setGroup(List<Fields> fields, Operator groupOper, Group group) {
		if (fields == null || fields.size() < 1) {
			return null;
		}
		Group tgroup = new Group(fields, groupOper, group);
		return tgroup;
	}

	/**
	 * 创建分组查询条件
	 * 
	 * @param field
	 *            :列封装数据
	 * @param groupOper
	 *            :组与组之间关系
	 * @return
	 */
	public static Group setGroup(Operator groupOper, Fields... field) {
		if (field == null || field.length < 1) {
			return null;
		}
		List<Fields> fileds = setFilesToList(field);
		Group group = setGroup(fileds, groupOper, null);
		return group;
	}

	/**
	 * 创建分组查询条件
	 * 
	 * @param fields
	 *            :对组列封装数据
	 * @param groupOper
	 *            :组与组之间关系
	 * @return
	 */
	public static Group setGroup(List<Fields> fields, Operator groupOper) {
		if (fields == null || fields.size() < 1) {
			return null;
		}
		Group group = setGroup(fields, groupOper, null);
		return group;
	}

	/**
	 * 创建分组查询条件
	 * 
	 * @param groups
	 *            ：分组数据
	 * @return
	 */
	public static List<Group> setGroupList(Group... groups) {
		List<Group> list = new ArrayList<Group>();
		if (groups == null && groups.length < 1) {
			return list;
		}
		for (Group group : groups) {
			if (group != null) {
				list.add(group);
			}
		}
		return list;
	}

	/**
	 * 创建查询条件
	 * 
	 * @param groups
	 *            ：分组数据
	 * @return
	 */
	public static Condition setCondition(List<Group> group) {
		if (group == null || group.size() < 1) {
			return new Condition();
		}
		Condition condition = new Condition(group);
		return condition;
	}

	/**
	 * 创建分页对象
	 * 
	 * @param pageIndex
	 *            ：开始页数
	 * @param pageCount
	 *            ：每页记录数
	 * @return
	 */
	public static Page setPage(int pageIndex, int pageCount) {
		Page page = new Page(pageIndex, pageCount);
		return page;
	}

	/**
	 * 分页查询所有，排序，分组
	 * 
	 * @param resourceType
	 *            :资源类型
	 * @param condition
	 *            ：查询条件
	 * @param page
	 *            ：分页
	 * @param orderBy
	 *            ：排序
	 * @param groupBy
	 *            ：分组
	 * @param beginTime
	 *            ：开始时间
	 * @param endTime
	 *            ：结束时间
	 * @return
	 */
	public static Root setRoot(ResourceType resourceType, Condition condition, Page page, String orderBy, String groupBy, String beginTime,
			String endTime) {
		Root root = new Root(resourceType, condition, page, orderBy, groupBy, beginTime, endTime);
		return root;
	}

	public static Root setRoot(ResourceType resourceType, Condition condition, Page page) {
		Root root = new Root(resourceType, condition, page, null, null, null, null);
		return root;
	}

	/**
	 * 分页查询所有，排序，分组
	 * 
	 * @param selectID
	 *            :是否根据id查询，默认为查询所有数据
	 * @param resourceType
	 *            :资源类型
	 * @param condition
	 *            ：查询条件
	 * @return
	 */
	public static Root setRoot(boolean selectID, ResourceType resourceType, Condition condition) {
		Root root = new Root(selectID, resourceType, condition);
		return root;
	}

	/**
	 * 获取查询条件之间关系
	 * 
	 * @param op
	 * @return
	 */
	private static String getOpertator(Operator op) {
		if (op == null) {
			return null;
		}
		String res = null;
		switch (op) {
		case equal:
			res = Operator.equal.getKey();
			break;
		case greater:
			res = Operator.greater.getKey();
			break;
		case greater_or_equal:
			res = Operator.greater_or_equal.getKey();
			break;
		case less:
			res = Operator.less.getKey();
			break;
		case less_or_equal:
			res = Operator.less_or_equal.getKey();
			break;
		case not_equal:
			res = Operator.not_equal.getKey();
			break;
		case leftMatch:
			res = Operator.leftMatch.getKey();
			break;
		case and:
			res = Operator.and.getKey();
			break;
		case or:
			res = Operator.or.getKey();
			break;
		default:
			break;
		}
		return res;
	}

	/**
	 * 拼接列值条件
	 * 
	 * @param groups
	 *            ：分组查询数据
	 * @return
	 */
	private static StringBuilder getFilesCondtion(List<Group> groups) {
		StringBuilder sub = new StringBuilder();
		if (groups == null || groups.size() < 1) {
			return null;
		}
		for (Group group : groups) {
			StringBuilder condtion = getFilesCondtion(group);
			if (condtion != null && condtion.length() > 0) {
				sub.append(condtion.toString());
			}
		}
		return sub;
	}

	/**
	 * 拼接列值条件
	 * 
	 * @param fields
	 * @return
	 */
	private static StringBuilder getFilesCondtion(Group group) {

		StringBuilder sub = new StringBuilder();
		if (group == null) {
			return sub;
		}
		List<Fields> fields = group.getFields();
		if (fields == null || fields.size() < 1) {
			return sub;
		}
		sub.append(" (");
		if (fields == null || fields.size() < 1) {
			return sub;
		}
		for (Fields fd : fields) {
			if (StringUtils.isNotBlank(fd.getField())) {
				sub.append(fd.getField()).append(" ");

				// 操作符
				String op = getOpertator(fd.getOp());
				if (StringUtils.isEmpty(op)) {
					sub.append("=").append(" ");
					sub.append("'" + fd.getValue() + "'").append(" ");
				} else if (op.indexOf("like") != -1) {
					sub.append(op).append(" ");
					sub.append("'" + fd.getValue() + "%'").append(" ");
				} else {
					sub.append(op).append(" ");
					sub.append("'" + fd.getValue() + "'").append(" ");
				}
				// 关系符
				if (fd.getOpt() != null) {
					String opt = getOpertator(fd.getOpt());
					opt = (opt == null || "".equals(opt)) ? "" : opt;
					sub.append(opt).append(" ");
				}
			}
		}
		sub.append(") ");

		// 拼接各查询条件之间的关系
		if (group.getOpt() != null) {
			String opt = getOpertator(group.getOpt());
			opt = (opt == null || "".equals(opt)) ? "" : opt;
			sub.append(opt).append(" ");
		}

		// 子查询条件
		Group group2 = group.getGroup();
		if (group2 != null) {
			StringBuilder condtion = getFilesCondtion(group2);
			if (condtion != null && condtion.length() > 0) {
				sub.append(condtion.toString()).append(" ");
			}
		} else {
			return sub;
		}
		return sub;
	}

	/**
	 * 拼接查询条件
	 */
	public static Map<String, Object> getCondition(Root root) {

		ResourceType resourceType = root.getResourceType();
		// 拼接查询条件
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("SelectID", root.getSelectID());

		// 资源类型
		if (resourceType != null) {
			map.put("ResourceType", resourceType.getValue());
		}
		// 排序
		String orderBy = root.getOrderBy();
		if (StringUtils.isNotBlank(orderBy)) {
			map.put("orderby", orderBy);
		}
		// 分组
		String groupby = root.getGroupBy();
		if (StringUtils.isNotBlank(groupby)) {
			map.put("groupby", groupby);
		}
		// 分页数据
		Page page = root.getPage();
		if (page != null) {
			map.put("pageIndex", page.getPageIndex());
			map.put("pageCount", page.getPageCount());
		}
		// 查询时间段
		String beginTime = root.getBeginTime();
		if (StringUtils.isNotBlank(beginTime)) {
			map.put("beginTime", beginTime);
		}
		String endTime = root.getEndTime();
		if (StringUtils.isNotBlank(endTime)) {
			map.put("endTime", endTime);
		}
		// 分组查询条件
		Condition condition = root.getCondition();
		if (condition == null) {
			return map;
		}
		// 拼接列值条件
		List<Group> groups = condition.getGroups();
		StringBuilder condsub = getFilesCondtion(groups);
		if (condsub != null) {
			String endsCond = condsub.toString().trim();
			if (endsCond.endsWith(Operator.and.getKey())) {
				condsub.append(" 1=1 ");
			} else if (endsCond.endsWith(Operator.or.getKey())) {
				condsub.append(" 1=1 ");
			}
			map.put("Condition", condsub.toString());
		}
		return map;
	}

	/**
	 * 封装返回数据
	 * 
	 * @param status
	 *            :状态
	 * @param msg
	 *            :消息
	 * @param total
	 *            ：总数
	 * @param time
	 *            :查询耗时
	 * @param list
	 *            ：查询数据集
	 */
	public static QueryDataVo<List<Map<String, Object>>> setQueryDataVo(int status, String msg, Long total, long time, List<Map<String, Object>> list) {
		QueryDataVo<List<Map<String, Object>>> dataVo = new QueryDataVo<List<Map<String, Object>>>();
		dataVo.setStatus(status);
		dataVo.setMsg(msg);
		dataVo.setNumFound(total);
		dataVo.setTime(time);
		dataVo.setDocs(list);
		return dataVo;
	}

	/**
	 * 封装返回数据
	 * 
	 * @param status
	 *            :状态
	 * @param msg
	 *            :消息
	 * @param total
	 *            ：总数
	 * @param time
	 *            :查询耗时
	 * @param list
	 *            ：查询数据集
	 */
	public static QueryDataVo<Map<String, Object>> setQueryDataVoToMap(int status, String msg, Long total, long time, Map<String, Object> map) {
		QueryDataVo<Map<String, Object>> dataVo = new QueryDataVo<Map<String, Object>>();
		dataVo.setStatus(status);
		dataVo.setMsg(msg);
		dataVo.setTime(time);
		dataVo.setDocs(map);
		return dataVo;
	}
}
